home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gnu / adainc / a-numran.adb < prev    next >
Text File  |  1996-01-30  |  8KB  |  257 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --                  A D A . N U M E R I C S . R A N D O M                   --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.3 $                              --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26. --  This implementation is derived from LSN 1055 written by Ken Dritz.
  27.  
  28. with Ada.Calendar;
  29.  
  30. package body Ada.Numerics.Random is
  31.  
  32.    ------------------------------
  33.    -- Form of the Image String --
  34.    ------------------------------
  35.  
  36.    --  The image string is of the form:
  37.  
  38.    --     nnn,nnn,nnn .... nnn,b
  39.  
  40.    --  There are Larger_Lag nnn components, where each component is a
  41.    --  decimal integer representing the values of the Lagged_Outputs in
  42.    --  the State_Vector, stored as rounded values * 2**24, in reverse order
  43.    --  (i.e. highest indexed value comes first), b is the borrow (0/1)
  44.  
  45.    -----------
  46.    -- Image --
  47.    -----------
  48.  
  49.    function Image (S : State) return String is
  50.       Result        : String (1 .. Max_Image_Width);
  51.       Result_Length : Natural;
  52.  
  53.       procedure Encode (Value : Float);
  54.       --  Add encoded float value to result string, using the float value
  55.       --  multiplied by 2**24 as a rounded decimal integer string.
  56.  
  57.       procedure Encode (Value : Float) is
  58.          Img : constant String := Int'Image (Int (2#1.0#E24 * Value));
  59.  
  60.       begin
  61.          for J in 2 .. Img'Length loop
  62.             Result_Length := Result_Length + 1;
  63.             Result (Result_Length) := Img (J);
  64.          end loop;
  65.       end Encode;
  66.  
  67.    --  Start processing for Image
  68.  
  69.    begin
  70.       Result_Length := 0;
  71.  
  72.       for J in Lag_Range loop
  73.          Encode (S.Lagged_Outputs (S.R - J));
  74.          Result_Length := Result_Length + 1;
  75.          Result (Result_Length) := ',';
  76.       end loop;
  77.  
  78.       Encode (S.Borrow);
  79.       return Result (1 .. Result_Length);
  80.    end Image;
  81.  
  82.    ----------------
  83.    -- Make_State --
  84.    ----------------
  85.  
  86.    function Make_State (Starter : Int := 3E+7) return State is
  87.       Bit_Value      : Float;
  88.       LCG_State      : Float;
  89.  
  90.       Result : State;
  91.  
  92.       function LCG_Random return Uniformly_Distributed;
  93.       --  Needs comments???
  94.  
  95.       function LCG_Random return Uniformly_Distributed is
  96.          LCG_Multiplier : constant := 16_807.0;
  97.          LCG_Modulus    : constant := 2_147_483_647.0;
  98.          T : Float;
  99.          J : Int;
  100.  
  101.       begin
  102.          T := LCG_State * LCG_Multiplier;
  103.          J := Int (T / LCG_Modulus);
  104.          LCG_State := T - Float (J) * LCG_Modulus;
  105.  
  106.          if LCG_State < 0.0 then
  107.             LCG_State := LCG_State + LCG_Modulus;
  108.          end if;
  109.  
  110.          return LCG_State / LCG_Modulus;
  111.       end LCG_Random;
  112.  
  113.    --  Start of processing for Make_State
  114.  
  115.    begin
  116.       LCG_State := Float (Starter);
  117.  
  118.       for J in Lag_Range loop
  119.          Result.Lagged_Outputs (J) := 0.0;
  120.          Bit_Value := 1.0;
  121.  
  122.          for K in 1 .. 24 loop
  123.             Bit_Value := Bit_Value * 0.5;
  124.  
  125.             if LCG_Random >= 0.5 then
  126.                Result.Lagged_Outputs (J) :=
  127.                  Result.Lagged_Outputs (J) + Bit_Value;
  128.             end if;
  129.          end loop;
  130.       end loop;
  131.  
  132.       Result.Borrow := 0.0;
  133.       Result.R      := Larger_Lag - 1;
  134.       Result.S      := Smaller_Lag - 1;
  135.       return Result;
  136.    end Make_State;
  137.  
  138.    ------------
  139.    -- Random --
  140.    ------------
  141.  
  142.    procedure Random (S : in out State; U : out Uniformly_Distributed) is
  143.       U1 : Uniformly_Distributed'Base;
  144.    begin
  145.       U1 := S.Lagged_Outputs (S.R) - S.Lagged_Outputs (S.S) - S.Borrow;
  146.  
  147.       if U1 < 0.0 then
  148.          U1 := U1 + 1.0;
  149.          S.Borrow := 2#1.0#e-24;
  150.       else
  151.          S.Borrow := 0.0;
  152.       end if;
  153.  
  154.       U := U1;
  155.       S.Lagged_Outputs (S.R) := U;
  156.       S.R := S.R - 1;
  157.       S.S := S.S - 1;
  158.    end Random;
  159.  
  160.    -----------
  161.    -- Reset --
  162.    -----------
  163.  
  164.    procedure Reset (S : out State; Initiator : in Integer) is
  165.    begin
  166.       S := Make_State (Int (Initiator) mod 2_147_483_646 + 1);
  167.    end Reset;
  168.  
  169.    procedure Reset (S : out State) is
  170.       use Ada.Calendar;
  171.  
  172.       Year  : Year_Number;
  173.       Month : Month_Number;
  174.       Day   : Day_Number;
  175.       Secs  : Day_Duration;
  176.  
  177.    begin
  178.       Split (Clock, Year, Month, Day, Secs);
  179.       S := Make_State (((Int (Year)   * 12 +
  180.                          Int (Month)) * 32 +
  181.                          Int (Day))   * 24 * 60 * 60 +
  182.                          Int (Secs));
  183.    end Reset;
  184.  
  185.    -----------
  186.    -- Value --
  187.    -----------
  188.  
  189.    function Value (S : String) return State is
  190.       Result : State;
  191.       Ptr    : Natural := S'First;
  192.  
  193.       function Decode_Component (Max : in Nat) return Float;
  194.       --  Decode next component as a floating-point value, by reading an
  195.       --  integer up to a comma or the end of the string, and converting
  196.       --  it to float by dividing by 2**24. Ptr is the initial location for
  197.       --  the scan, and is advanced past the termninator. Max is the maximum
  198.       --  value of the component as an integer (2**24 - 1 for the lagged
  199.       --  components, and 1 for the borrow).
  200.  
  201.       function Decode_Component (Max : in Nat) return Float is
  202.          End_Ptr : Natural;
  203.          Int_Val : Nat;
  204.  
  205.       begin
  206.          --  Not enough components if past end of string
  207.  
  208.          if Ptr > S'Last then
  209.             raise Constraint_Error;
  210.          end if;
  211.  
  212.          End_Ptr := Ptr;
  213.  
  214.          while End_Ptr <= S'Last
  215.            and then S (End_Ptr) /= ','
  216.          loop
  217.             End_Ptr := End_Ptr + 1;
  218.          end loop;
  219.  
  220.          --  Make sure Length is in reasonable bounds (2**24 < 10**8)
  221.  
  222.          if End_Ptr = Ptr or else End_Ptr > Ptr + 8 then
  223.             raise Constraint_Error;
  224.          end if;
  225.  
  226.          Int_Val := Nat'Value (S (Ptr .. End_Ptr - 1));
  227.  
  228.          if Int_Val > Max then
  229.             raise Constraint_Error;
  230.          end if;
  231.  
  232.          Ptr := End_Ptr;
  233.          return Float (Int_Val) * 2#1.0#e-24;
  234.       end Decode_Component;
  235.  
  236.    --  Start of processing for Value
  237.  
  238.    begin
  239.       for J in reverse Lag_Range loop
  240.          Result.Lagged_Outputs (J) := Decode_Component (2**24 - 1);
  241.       end loop;
  242.  
  243.       Result.Borrow := Decode_Component (1);
  244.  
  245.       --  Must be at end of string now!
  246.  
  247.       if Ptr <= S'Last then
  248.          raise Constraint_Error;
  249.       end if;
  250.  
  251.       Result.R := Larger_Lag - 1;
  252.       Result.S := Smaller_Lag - 1;
  253.       return Result;
  254.    end Value;
  255.  
  256. end Ada.Numerics.Random;
  257.